/*
 * Copyright 2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dailydev.wave.robot.servlet;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

import org.dailydev.wave.robot.IRobot;
import org.dailydev.wave.robot.Robot;
import org.dailydev.wave.robot.filter.IFilter;
import org.dailydev.wave.robot.filter.SimpleFilterManager;

/**
 * Implementation of {@link IRobotFactory} returning same instance for all
 * {@link AbstractSingletonRobotFactory#buildRobot(ServletContext)} calls.
 * 
 * @author Roman Bosak, DailyDev.org
 */
public abstract class AbstractSingletonRobotFactory implements IRobotFactory {

    private static Robot robot;

    /** {@inheritDoc} */
    @Override
    public final synchronized IRobot buildRobot(ServletConfig config) {
        if (robot == null) {
            robot = new Robot();

            Object[] handlers = getHandlers(config);
            if (handlers != null) {
                robot.setHandlers(new HashSet<Object>(Arrays.asList(handlers)));
            }

            IFilter[] filters = getFilters(config);
            if (filters != null) {
                robot.setFilterManager(new SimpleFilterManager(new ArrayList<IFilter>(Arrays.asList(filters))));
            }

            robot.setRobotName(getRobotName(config));
            robot.setRobotVersion(getRobotVersion(config));
            robot.setRobotAvatar(getRobotAvatar(config));
        }
        return robot;
    }

    /**
     * Returns robot's name. Default implementation gets value from servlet's
     * context init parameter '<code>robot.name</code>'.
     * 
     * @param config
     * @return robot's name
     */
    protected String getRobotName(ServletConfig config) {
        return config.getServletContext().getInitParameter("robot.name");
    }

    /**
     * Returns robot's version. Default implementation gets value from servlet's
     * context init parameter '<code>robot.version</code>'.
     * 
     * @param config
     * @return robot's version
     */
    protected String getRobotVersion(ServletConfig config) {
        return config.getServletContext().getInitParameter("robot.version");
    }

    /**
     * Returns robot's avatar URI. Default implementation gets value from
     * servlet's context init parameter '<code>robot.avatar</code>'.
     * 
     * @param config
     * @return robot's avatar URI
     */
    protected String getRobotAvatar(ServletConfig config) {
        return config.getServletContext().getInitParameter("robot.avatar");
    }

    /**
     * Method should be implemented by subclasses to specify set of handlers to
     * be handled by robot.
     * 
     * @return set of handlers to be handled by robot
     */
    protected abstract Object[] getHandlers(ServletConfig config);

    /**
     * Method can be implemented by subclasses to specify list of
     * {@link IFilter}s to be applied before handler method call.
     * 
     * @return set of handlers to be handled by robot
     */
    protected IFilter[] getFilters(ServletConfig config) {
        return null;
    }
}
